package com.hg.library.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout;

import com.hg.highglass_library.R;

/**
 * Created by wangjianqiang on 2016/9/6.
 */
public class HaloRelativeLayout extends RelativeLayout {
    private boolean hasFocus = false;
    private EffectThread effectThreadl;
    private Paint paint;
    private Bitmap bitmap;
    private float pointX = 0;
    private float initX = 0;
    private float bitmapWidth = 0;
    private float tan = 0;
    private double degree = 0;
    private float unit = 0;
    private int speed = 150;//值越大，越慢
    private boolean setBold = false;//是否设置边界
    private int scale_num = 1;//光晕缩小倍数
    private int left = 0, top = 0, right = 0, bottom = 0;
    private boolean setDegree = false;
    private int multiNum = 1;//防止出现光晕不完全现象
    private int leftMargin = -1;//原点距离
    private boolean disableStateChanged = false;//是否使用系统自动机制

    public HaloRelativeLayout(Context context) {
        this(context, null);
    }

    public HaloRelativeLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HaloRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        if (attrs != null) {
            final TypedArray a = context.obtainStyledAttributes(
                    attrs, R.styleable.haloeffect, defStyleAttr, 0);
            left = (int) a.getDimension(R.styleable.haloeffect_left_clip, 0f);
            top = (int) a.getDimension(R.styleable.haloeffect_top_clip, 0f);
            right = (int) a.getDimension(R.styleable.haloeffect_right_clip, 0f);
            bottom = (int) a.getDimension(R.styleable.haloeffect_bottom_clip, 0f);
            leftMargin = (int) a.getDimension(R.styleable.haloeffect_left_margain, -1);
            setSetBold(left, top, right, bottom);
            scale_num = a.getInteger(R.styleable.haloeffect_scale_num, 1);
            degree = a.getInteger(R.styleable.haloeffect_degree, 0) * Math.PI / 180;
            if (degree != 0) {
                setDegree = true;
            }
            multiNum = a.getInteger(R.styleable.haloeffect_multi_num, 1);
            speed = a.getInteger(R.styleable.haloeffect_speed, 150);
            disableStateChanged = a.getBoolean(R.styleable.haloeffect_disablestatechanged,false);
        }
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);
        if (scale_num == 1 || scale_num < 1) {
            scale_num = 1;
            bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.light_effect);
            bitmapWidth = bitmap.getWidth();
        } else {
            setScaleNum(scale_num);
        }
    }

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        if(disableStateChanged){
            return;
        }
        int[] states = getDrawableState();
        boolean selected = false;
        for (int i = 0; i < states.length; i++) {
            switch (states[i]) {
                case com.android.internal.R.attr.state_pressed:
                    selected = true;
                    break;
                case com.android.internal.R.attr.state_selected:
                    selected = true;
                    break;
                case com.android.internal.R.attr.state_focused:
                    selected = true;
                    break;
                case com.android.internal.R.attr.state_checked:
                    selected = true;
                    break;
                case com.android.internal.R.attr.state_hovered:
                    selected = true;
                    break;
            }
        }
        setHasFocus(selected);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (effectThreadl != null && effectThreadl.isAlive()) {
            effectThreadl.setCanRun(false);
        }

        if (!bitmap.isRecycled())
            bitmap.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (hasFocus && tan > 0) {
            canvas.save();
            if (setBold) {
                canvas.clipRect(left, top, getWidth() - right, getHeight() - bottom);
            }
            canvas.translate(getWidth() / 2, getHeight() / 2);
            canvas.rotate(90 - (float) (degree / Math.PI * 180));
            canvas.translate(-getWidth() / 2, -getHeight() / 2);
            canvas.drawBitmap(bitmap, pointX, -multiNum * getHeight(), paint);
            canvas.restore();
        }

    }

    public void setHasFocus(final boolean hasFocus) {

        this.hasFocus = hasFocus;
        if (hasFocus) {
            if (hasFocus) {
                if (effectThreadl != null && effectThreadl.isAlive()) {
                    effectThreadl.setCanRun(false);
                    effectThreadl.interrupt();
                    effectThreadl = null;
                }
                effectThreadl = new EffectThread();
                effectThreadl.start();
            }
        } else {
            pointX = initX;
            invalidate();
        }
    }

    private class EffectThread extends Thread {
        private boolean canRun = true;

        public void setCanRun(boolean canRun) {
            this.canRun = canRun;
        }

        @Override
        public void run() {
            super.run();
            while (canRun && hasFocus) {
                if (tan == 0) {
                    if (getHeight() != 0 && getWidth() != 0) {
                        tan = (float) getHeight() / getWidth();
                        if (!setDegree) {
                            degree = Math.atan(tan);
                        }
                        if (leftMargin == -1) {
                            leftMargin = getWidth();
                        }
                        initX = -(float) (bitmapWidth * Math.cos(degree)) - leftMargin;
                        pointX = initX;
                        unit = (float) (getHeight() / Math.sin(degree) / speed);
                    }
                } else {
                    pointX = pointX + (float) (unit * Math.cos(degree));
                    if (pointX >= getWidth()) {
                        pointX = initX;
                    }
                }
                postInvalidate();
                try {
                    Thread.sleep(20);
                } catch (Exception e) {
                }
            }
        }

    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public void setScaleNum(int num) {
        Bitmap effect = BitmapFactory.decodeResource(getResources(), R.drawable.light_effect);
        bitmap = Bitmap.createScaledBitmap(effect, effect.getWidth() / num, effect.getHeight(), true);
        bitmapWidth = bitmap.getWidth();
        effect.recycle();
    }

    public void setSetBold(int left, int top, int right, int bottom) {
        if (left != 0 || top != 0 || right != 0 || bottom != 0) {
            setBold = true;
            this.left = left;
            this.right = right;
            this.top = top;
            this.bottom = bottom;
        }
    }

    public void setDegree(double degree) {
        setDegree = true;
        this.degree = degree * Math.PI / 180;
        tan = 0;
    }

    public void setMultiHeightNum(int num) {
        this.multiNum = num;
    }

    public void setLeftMargin(int leftMargin) {
        this.leftMargin = leftMargin;
        tan = 0;
    }

    public void setDisableStateChanged(boolean disableStateChanged) {
        this.disableStateChanged = disableStateChanged;
    }
}
